
# Copyright 2016 Nervana Systems Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

[-
our $type;
our $dtype       = $type eq 'h' ?         'U16' :  '32';
our $convert_in  = $type eq 'h' ? 'F2F.F32.F16' :    '';
our $convert_out = $type eq 'h' ? 'F2F.F16.F32' :    '';
our $dshift      = $type eq 'h' ?           '1' :   '2';
our $dsize       = $type eq 'h' ?           '2' :   '4';
our $vsize       = $type eq 'h' ?          '64' : '128';
sub dtype  { return $dtype;  }
sub dsize  { return $dsize;  }
sub dshift { return $dshift; }
sub vsize  { return $vsize;  }
-]

<CONSTANT_MAPPING>

    addr_zero   : 4x<32*36*2*4 + 64 + 0>
    addr_idx_Y  : 4x<32*36*2*4 + 64 + 4>
    addr_idx_X  : 4x<32*36*2*4 + 64 + 5>
    addr_idx_K  : 4x<32*36*2*4 + 64 + 6>

    param_S[0]           : c[0x0][0x140]
    param_S[1]           : c[0x0][0x144]
    param_X[0]           : c[0x0][0x148]
    param_X[1]           : c[0x0][0x14c]
    param_O[0]           : c[0x0][0x150]
    param_O[1]           : c[0x0][0x154]
    param_I[0]           : c[0x0][0x158]
    param_I[1]           : c[0x0][0x15c]
    param_F[0]           : c[0x0][0x160]
    param_F[1]           : c[0x0][0x164]
    param_alpha          : c[0x0][0x168]
    param_beta           : c[0x0][0x16c]
    param_flags          : c[0x0][0x170]
    param_C              : c[0x0][0x174]
    param_K              : c[0x0][0x178]
    param_N              : c[0x0][0x17c]
    param_Y              : c[0x0][0x180]
    param_W              : c[0x0][0x184]
    param_YXN            : c[0x0][0x188]
    param_XN             : c[0x0][0x18c]
    param_Y2             : c[0x0][0x190]
    param_GX             : c[0x0][0x194]
    param_Xk             : c[0x0][0x198]
    param_k              : c[0x0][0x19c]
    param_magic_Xk       : c[0x0][0x1a0]
    param_shift_Xk       : c[0x0][0x1a4]
    param_magic_k        : c[0x0][0x1a8]
    param_shift_k        : c[0x0][0x1ac]
    param_P              : c[0x0][0x1b0]
    param_Q              : c[0x0][0x1b4]
    param_QN             : c[0x0][0x1b8]
    param_PQN            : c[0x0][0x1bc]
    param_PQN15          : c[0x0][0x1c0]
    param_maskN          : c[0x0][0x1c4]
    param_shiftX         : c[0x0][0x1c8]
    param_shiftY         : c[0x0][0x1cc]
    param_superX         : c[0x0][0x1d0]
    param_superY         : c[0x0][0x1d4]
    param_pad_x          : c[0x0][0x1d8]
    param_pad_y          : c[0x0][0x1dc]
    param_RSK            : c[0x0][0x1e0]
    param_RSK2p          : c[0x0][0x1e4]
    param_YXN2p          : c[0x0][0x1e8]
    param_gridN          : c[0x0][0x1ec]
    param_gridQN         : c[0x0][0x1f0]
    param_gridPQN        : c[0x0][0x1f4]
</CONSTANT_MAPPING>

<REGISTER_MAPPING>

       0-63 : czero<00-63>

     3, 2,11,10 : clx<0-3>y0
     7, 6,15,14 : clx<0-3>y1
     1, 0, 9, 8 : clx<0-3>y2
     5, 4,13,12 : clx<0-3>y3
    19,18,27,26 : clx<0-3>y4
    23,22,31,30 : clx<0-3>y5
    17,16,25,24 : clx<0-3>y6
    21,20,29,28 : clx<0-3>y7

      32-43 : jl0Ix<0-3>, jl0Fy<0-7>
      44-51 : jl1Ix<0-3>, jl1Fy<4-7>
      36-39 : jl1Fy<0-3>

      32-43 ~ swapBuff

      88-89 : track<0-1>
      90-92 : writeS, pred30, pred36

      // Image Transform
      44-51 ~ ti<0-5>

      52,53,54,56,57,55 : i<0-5>0
      59,60,61,63,58,62 : i<0-5>1
      66,67,68,64,65,69 : i<0-5>2
      73,74,75,71,72,70 : i<0-5>3
      87,82,83,85,86,84 : i<0-5>4
      80,81,76,78,79,77 : i<0-5>5

      52,53,54,56,57,55 : TI<0-5>0
      59,60,61,63,58,62 : TI<0-5>1
      66,67,68,64,65,69 : TI<0-5>2
      73,74,75,71,72,70 : TI<0-5>3
      87,82,83,85,86,84 : TI<0-5>4
      80,81,76,78,79,77 : TI<0-5>5

      52,53,54,56,57,55 : I<0-5>0
      59,60,61,63,58,62 : I<0-5>1
      66,67,68,64,65,69 : I<0-5>2
      73,74,75,71,72,70 : I<0-5>3
      87,82,83,85,86,84 : I<0-5>4
      80,81,76,78,79,77 : I<0-5>5

      // Filter Transform
      44-47 ~ rcp6, rcp8, rcp12, rcp24

      52,53,54 : f<0-2>0
      55,56,57 : f<0-2>1
      58,59,60 : f<0-2>2

      61,62,63 : tf<0-2>0
      64,65,66 : tf<0-2>1
      67,68,69 : tf<0-2>2

      70,71,72,73,74,54 : TF<0-5>0
      76,77,78,79,80,57 : TF<0-5>1
      82,83,84,85,86,60 : TF<0-5>2

      61,64,48,49,50,51 : ff<0-5>0
      52,53,55,56,58,59 : ff<0-5>1
      61,64,48,49,50,51 : ff<0-5>2

      70,71,72,73,74,54 : F<0-5>0
      62,63,65,66,67,68 : F<0-5>1
      52,53,55,56,58,59 : F<0-5>2
      69,75,81,87,76,77 : F<0-5>3
      61,64,78,79,80,57 : F<0-5>4
      82,83,84,85,86,60 : F<0-5>5

      32-39 ~ partialC, idx_K, idx_Y, idx_X
      40-86 ~ idx_KYXk, idx_YXk, idx_Xk, idx_k, idx_Y2, idx_X2, div<1-3>, magic_YXk, negYXk, magic_Xk, negXk, tid32_2, tid1, tid31, gx, gy, c, kk, offset, sign, idx_N, nn, x<1-5>, mask_x, super_x, super_y, partC

      32-39 : shuffle16_x<0-3>y0, shuffle16_x<0-3>y1
      48-91 ~ Tid, Tid1, Tid32_2, write16Cs, alpha16


     3, 2,11,10,19,18,27,26 : ccx<0-7>y0
     7, 6,15,14,23,22,31,30 : ccx<0-7>y1
     1, 0, 9, 8,17,16,25,24 : ccx<0-7>y2
     5, 4,13,12,21,20,29,28 : ccx<0-7>y3
    35,34,43,42,51,50,59,58 : ccx<0-7>y4
    39,38,47,46,55,54,63,62 : ccx<0-7>y5
    33,32,41,40,49,48,57,56 : ccx<0-7>y6
    37,36,45,44,53,52,61,60 : ccx<0-7>y7

      64-79 : jc0Ix<0-7>, jc0Fy<0-7>
      80-91 : jc1Ix<4-7>, jc1Fy<0-7>
      64-67 : jc1Ix<0-3>

      64-86 ~ tid16, tid_1, tid128
         92 = swapBuf

         87 = tid
      93-95 ~ C, readFs, readIs

      64-85 ~ tid_128, tid_64, tid_32, tid_31, tid_16, Tid_1, idxN, idxX, idxY, idxK, readFs2, readIs2, p, q, n, z<1-3>, mask_q
      86-95 ~ alpha, one, writeCs, readCs, k, preds, offsetO, bias, bsum_offset

      64-79 : shuffle_x<0-7>y0, shuffle_x<0-7>y1

      // t00 80      r00 78
      // t10 m10     r01 w01
      // t20 m20     r02 w02
      // t30 m30     r03 w03
      // w00 m00     s00 w00
      // w30 m40     s01 w01
      // w10 m10     s02 w02
      // w20 m20     s03 w04

      78 = t0<0-5>, r<0-3>0
      79 = temp

       3, 2,11,10,19,18 : m<0-5>0
       1, 9, 0, 8,17,16 : m<0-5>1
      27,26,25,24,64,65 : m<0-5>2
                2,11,10 : t10, t20, t30
                9, 0, 8 : t11, t21, t31
               26,25,24 : t12, t22, t32
             3, 2,11,19 : w00, w10, w20, w30
             1, 9, 0,17 : w01, w11, w21, w31
            27,26,25,64 : w02, w12, w22, w32

      66,67,68,69,70,71 : m<0-5>3
      72,73,74,75,76,77 : m<0-5>4
       8,24,10,65,16,18 : m<0-5>5
               67,68,69 : t13, t23, t33
               73,74,75 : t14, t24, t34
               24,10,65 : t15, t25, t35
            66,67,68,70 : w03, w13, w23, w33
            72,73,74,76 : w04, w14, w24, w34
             8,24,10,16 : w05, w15, w25, w35

                1,27,66 : r01, r02, r03
                9,26,67 : r11, r12, r13
                0,25,68 : r21, r22, r23
               17,64,70 : r31, r32, r33
             3, 1,27,72 : s00, s01, s02, s03
             2, 9,26,73 : s10, s11, s12, s13
            11, 0,25,74 : s20, s21, s22, s23
            19,17,64,76 : s30, s31, s32, s33

                  80-83 ~ xx<0-3>
                  78-81 ~ sum<0-3>
                  82-83 : Sum<0-1>
                  84-85 : Out<0-1>

             8,10,16,18 ~ b0<0-3>
            24,65,66,67 ~ b1<0-3>
            68,69,70,71 ~ b2<0-3>
            75,77,78,79 ~ b3<0-3>

</REGISTER_MAPPING>

--:-:-:-:0      MOV C,   param_C;
--:-:1:-:2      S2R tid, SR_TID.X;
01:-:-:-:0      ISETP.GE.AND P0, PT, tid, 128, PT;
--:-:-:-:1      STS.128 [addr_zero], RZ;
--:-:-:Y:c      LOP.AND partialC, C, 1;
--:-:-:-:0      IADD C, C, partialC;
--:-:-:-:5  @P0 BRA.U COMPUTE_SETUP;

##############################################################
LOAD_SETUP:

--:-:1:-:1      S2R idx_YXk, SR_CTAID.X;
--:-:2:-:1      S2R idx_K,   SR_CTAID.Y;

<SCHEDULE_BLOCK>

[+ join '', map sprintf("--:-:-:-:1      LDS.U.128 czero%02d, [addr_zero];\n", $_ * 4), 0..7; +]

--:-:-:-:1      ISETP.EQ.AND P0, PT, tid, RZ, PT;
--:-:-:-:1      ISETP.GE.AND P1, PT, tid, 64, PT;

// idx_Y2   = idx_YXk / blk_Xk
--:-:-:-:1      MOV  magic_Xk, param_magic_Xk;
--:-:-:-:1      IADD negXk, RZ, -param_Xk;
--:-:-:-:1      ISETP.NE.AND P3, PT, magic_Xk, 1, PT;
01:-:-:-:1  @P3 XMAD     div1, idx_YXk,    magic_Xk,    RZ;
--:-:-:-:1  @P3 XMAD     div2, idx_YXk,    magic_Xk.H1, RZ;
--:-:-:-:1  @P3 XMAD     div3, idx_YXk.H1, magic_Xk.H1, RZ;
--:-:-:-:1  @P3 XMAD.CHI div1, idx_YXk.H1, magic_Xk,    div1;
--:-:-:-:1  @P3 IADD3.RS idx_Y2, div1, div2, div3;
--:-:-:-:1  @P3 SHR.U32  idx_Y2, idx_Y2,  param_shift_Xk;
--:-:-:-:1 @!P3 SHR.U32  idx_Y2, idx_YXk, param_shift_Xk;

// idx_Xk  = idx_YXk % blk_Xk
--:-:-:-:1      XMAD.LO2 idx_Xk, negXk, idx_Y2, idx_YXk;

// idx_X2   = idx_Xk / blk_k
// idx_k   = idx_Xk % blk_k
--:-:-:-:1      XMAD    idx_X2,  idx_Xk, param_magic_k, RZ;
--:-:-:-:1      SHR.U32 idx_X2,  idx_X2, param_shift_k;
--:-:-:-:1      XMAD    idx_k,   idx_X2, param_k, RZ;
--:-:-:-:1      IADD    idx_k,  -idx_k,  idx_Xk;

// idx_K = idx_K * blk_k + idx_k
02:-:-:-:1      XMAD idx_K, idx_K, param_k, idx_k;

// gx = x2
// gy = y2 * 2
--:-:-:-:1      MOV idx_X, idx_X2;
--:-:-:-:1      SHL idx_Y, idx_Y2, 1;

// Implement a square wave block id remapping (for all but last row (if odd number of rows))
// if y2 != Y2:
//     gy += (gx&1) ^ ((gx&2)>>1)
//     gx /= 2
--:-:-:-:1      ISETP.NE.AND P4, PT, idx_Y2, param_Y2, PT;
--:-:-:-:1  @P4 LOP.AND x1, idx_X, 1;
--:-:-:-:1  @P4 BFE.U32 x2, idx_X, 0x101; // 1 bit at position 1
--:-:-:-:1  @P4 LOP.XOR x1, x1, x2;
--:-:-:-:1  @P4 IADD idx_Y, idx_Y, x1;
--:-:-:-:1  @P4 SHR.U32 idx_X, idx_X, 1;

// Scan backwards on odd rows
// if y2 & 1:
//     gx = gridX - gx - 1
--:-:-:-:1      LOP.AND.NZ P5, RZ, idx_Y2, 1;
--:-:-:-:1  @P5 IADD idx_X, -idx_X,  param_GX;
--:-:-:-:1  @P5 IADD idx_X,  idx_X, -1;

--:6:-:-:1  @P0 STS [addr_idx_Y], idx_Y;
--:6:-:-:1  @P0 STS [addr_idx_X], idx_X;
--:6:-:-:1  @P0 STS [addr_idx_K], idx_K;

// x = gx << shiftX
// y = gy << shiftY
--:-:-:-:1      SHL gx, idx_X, param_shiftX;
--:-:-:-:1      SHL gy, idx_Y, param_shiftY;

// Distribute the 8|4|2|1 blocks of the super block among 4|8|16|32 threads each of the warp
--:-:-:-:1      BFE.U32 super_x, tid, param_superX;
--:-:-:-:1      BFE.U32 super_y, tid, param_superY;
--:-:-:-:1      ISCADD gx, super_x,  gx, 2;
--:-:-:-:1      ISCADD gy, super_y,  gy, 2;

--:-:-:-:1      LOP.AND  tid32_2,  tid,   -32;
--:-:-:-:1      SHR.U32  tid32_2,  tid32_2, 2;

// readIs = ((tid & -32) >> 2) | ((tid >> 1) & 7)
--:-:-:-:1      BFE.U32 readIs, tid,    0x301; // 3 bits at position 1
--:-:-:-:1      LOP.OR  readIs, readIs, tid32_2;
--:-:-:-:1      SHL     readIs, readIs, 4;

// readFs = ((tid & -32) >> 2) | ((tid & 16) >> 3) | (tid & 1)
--:-:-:-:1      LOP.AND tid1,   tid,    1;
--:-:-:-:1      LOP.AND readFs, tid,    16;
--:-:-:-:1      SHR.U32 readFs, readFs, 3;
--:-:-:-:1      IADD3   readFs, readFs, tid1, tid32_2;
--:-:-:-:1      ISCADD  readFs, readFs, 4x<32*36*2>, 4;

// c = (tid & 32) >> 5
--:-:-:-:1      BFE.U32 c, tid, 0x105; // 1 bits at position 5

// writeS = c*32*36 + tid & 31
--:-:-:-:1      LOP.AND tid31, tid, 31;
--:-:-:-:1      XMAD writeS, c, 1152, tid31;
--:-:-:-:1      SHL writeS, writeS, 2;

</SCHEDULE_BLOCK>

--:-:-:-:5  @P1 BRA.U FILTER_SETUP;

##############################################################
IMAGE_SETUP:

--:-:1:-:1      S2R idx_N, SR_CTAID.Z;
<SCHEDULE_BLOCK>

--:-:-:-:1      STS [writeS + 4x<32*0>], RZ;
--:-:-:-:1      STS [writeS + 4x<32*1>], RZ;
--:-:-:-:1      STS [writeS + 4x<32*2>], RZ;
--:-:-:-:1      STS [writeS + 4x<32*3>], RZ;

// n = idx_N*32 + tid & maskN
--:-:-:-:1      LOP.AND nn, tid, param_maskN;
01:-:-:-:1      ISCADD  nn, idx_N, nn, 5;

// n < N
--:-:-:-:1      ISETP.LT.AND P6, PT, nn, param_N, PT;

// Subtract off the padding
--:-:-:-:1      IADD gx, gx, -param_pad_x;
--:-:-:-:1      IADD gy, gy, -param_pad_y;

// offset = c*YXN + y0*XN + x0*N + n;
--:-:-:-:1      XMAD.S16.U16      offset, gx, param_N,   nn;
--:-:-:-:1      XMAD.S16.U16.LO2C offset, gy, param_XN,  offset;
--:-:-:-:1      XMAD.S16.U16.LO2C offset, c,  param_YXN, offset;
--:-:-:-:1      ISET.LT.AND sign, offset, RZ, PT;

--:-:-:-:1      LEA    track0.CC, offset, param_I[0], [+ dshift() +];
--:-:-:-:1      IADD.X track1,    sign,   param_I[1];

--:-:-:-:1      IADD x1, gx, 1;
--:-:-:-:1      IADD x2, gx, 2;
--:-:-:-:1      IADD x3, gx, 3;
--:-:-:-:1      IADD x4, gx, 4;
--:-:-:-:1      IADD x5, gx, 5;

--:-:-:-:1      ISETP.LT.AND P0, PT, gx, param_W, PT;
--:-:-:-:1      ISETP.LT.AND P1, PT, x1, param_W, PT;
--:-:-:-:1      ISETP.LT.AND P2, PT, x2, param_W, PT;
--:-:-:-:1      ISETP.LT.AND P3, PT, x3, param_W, PT;
--:-:-:-:1      ISETP.LT.AND P4, PT, x4, param_W, PT;
--:-:-:-:1      ISETP.LT.AND P5, PT, x5, param_W, PT;
--:-:-:-:1      ISETP.GE.AND P0, PT, gx, RZ, P0;
--:-:-:-:1      ISETP.GE.AND P1, PT, x1, RZ, P1;
--:-:-:-:1      ISETP.GE.AND P2, PT, x2, RZ, P2;
--:-:-:-:1      ISETP.GE.AND P3, PT, x3, RZ, P3;
--:-:-:-:1      ISETP.GE.AND P4, PT, x4, RZ, P4;
--:-:-:-:1      ISETP.GE.AND P5, PT, x5, RZ, P5;
--:-:-:-:1      P2R mask_x, PR, RZ, 0x3f;

--:-:-:-:1      IADD x1, gy, 1;
--:-:-:-:1      IADD x2, gy, 2;
--:-:-:-:1      IADD x3, gy, 3;
--:-:-:-:1      IADD x4, gy, 4;
--:-:-:-:1      IADD x5, gy, 5;
--:-:-:-:1      ISETP.LT.AND P0, PT, gy, param_Y, P6;
--:-:-:-:1      ISETP.LT.AND P1, PT, x1, param_Y, P6;
--:-:-:-:1      ISETP.LT.AND P2, PT, x2, param_Y, P6;
--:-:-:-:1      ISETP.LT.AND P3, PT, x3, param_Y, P6;
--:-:-:-:1      ISETP.LT.AND P4, PT, x4, param_Y, P6;
--:-:-:-:1      ISETP.LT.AND P5, PT, x5, param_Y, P6;
--:-:-:-:1      ISETP.GE.AND P0, PT, gy, RZ, P0;
--:-:-:-:1      ISETP.GE.AND P1, PT, x1, RZ, P1;
--:-:-:-:1      ISETP.GE.AND P2, PT, x2, RZ, P2;
--:-:-:-:1      ISETP.GE.AND P3, PT, x3, RZ, P3;
--:-:-:-:1      ISETP.GE.AND P4, PT, x4, RZ, P4;
--:-:-:-:1      ISETP.GE.AND P5, PT, x5, RZ, P5;

--:-:-:-:1      SEL pred30, mask_x, RZ, P0;
--:-:-:-:1  @P1 BFI pred30, mask_x, 0x606, pred30;
--:-:-:-:1  @P2 BFI pred30, mask_x, 0x60c, pred30;
--:-:-:-:1  @P3 BFI pred30, mask_x, 0x612, pred30;
--:-:-:-:1  @P4 BFI pred30, mask_x, 0x618, pred30;
--:-:-:-:1      SEL pred36, mask_x, RZ, P5;

// P6 = c == partialC == 1
--:-:-:-:1      ISETP.EQ.AND P6, PT, c, 1, PT;
--:-:-:-:1      ISETP.EQ.AND P6, PT, c, partialC, P6;
--:-:-:-:1      XMAD     partC,    partialC, param_YXN,       RZ;
--:-:-:-:1      XMAD.PSL partialC, partialC, param_YXN.H1, partC;
--:-:-:-:1      SHL  partialC, partialC, [+ dshift() +];

--:-:-:-:1 @!P6 R2P PR, pred30, 0x3f;
--:-:-:-:1  @P6 R2P PR,     RZ, 0x3f;
--:-:-:-:1 @!P6 SHF.R.U64 pred30, pred30, 6, pred30;
20:-:-:-:1 @!P0 MOV i00, RZ;
--:-:-:-:1 @!P1 MOV i01, RZ;
--:-:-:-:1 @!P2 MOV i02, RZ;
--:-:-:-:1 @!P3 MOV i03, RZ;
--:-:-:-:1 @!P4 MOV i04, RZ;
--:-:-:-:1 @!P5 MOV i05, RZ;
--:-:-:-:1  @P0 LDG.E.CI.[+ dtype() +] i00, [track + [+ dsize() +]x<0*$W*$N + 0*$N>];
--:-:-:-:1  @P1 LDG.E.CI.[+ dtype() +] i01, [track + [+ dsize() +]x<0*$W*$N + 1*$N>];
--:-:-:-:1  @P2 LDG.E.CI.[+ dtype() +] i02, [track + [+ dsize() +]x<0*$W*$N + 2*$N>];
--:-:-:-:1  @P3 LDG.E.CI.[+ dtype() +] i03, [track + [+ dsize() +]x<0*$W*$N + 3*$N>];
--:-:-:-:1  @P4 LDG.E.CI.[+ dtype() +] i04, [track + [+ dsize() +]x<0*$W*$N + 4*$N>];
--:-:1:-:1  @P5 LDG.E.CI.[+ dtype() +] i05, [track + [+ dsize() +]x<0*$W*$N + 5*$N>];

--:-:-:-:1 @!P6 R2P PR, pred30, 0x3f;
--:-:-:-:1  @P6 R2P PR,     RZ, 0x3f;
--:-:-:-:1 @!P6 SHF.R.U64 pred30, pred30, 6, pred30;
--:-:-:-:1 @!P0 MOV i10, RZ;
--:-:-:-:1 @!P1 MOV i11, RZ;
--:-:-:-:1 @!P2 MOV i12, RZ;
--:-:-:-:1 @!P3 MOV i13, RZ;
--:-:-:-:1 @!P4 MOV i14, RZ;
--:-:-:-:1 @!P5 MOV i15, RZ;
--:-:-:-:1  @P0 LDG.E.CI.[+ dtype() +] i10, [track + [+ dsize() +]x<1*$W*$N + 0*$N>];
--:-:-:-:1  @P1 LDG.E.CI.[+ dtype() +] i11, [track + [+ dsize() +]x<1*$W*$N + 1*$N>];
--:-:-:-:1  @P2 LDG.E.CI.[+ dtype() +] i12, [track + [+ dsize() +]x<1*$W*$N + 2*$N>];
--:-:-:-:1  @P3 LDG.E.CI.[+ dtype() +] i13, [track + [+ dsize() +]x<1*$W*$N + 3*$N>];
--:-:-:-:1  @P4 LDG.E.CI.[+ dtype() +] i14, [track + [+ dsize() +]x<1*$W*$N + 4*$N>];
--:-:2:-:1  @P5 LDG.E.CI.[+ dtype() +] i15, [track + [+ dsize() +]x<1*$W*$N + 5*$N>];

--:-:-:-:1 @!P6 R2P PR, pred30, 0x3f;
--:-:-:-:1  @P6 R2P PR,     RZ, 0x3f;
--:-:-:-:1 @!P6 SHF.R.U64 pred30, pred30, 6, pred30;
--:-:-:-:1 @!P0 MOV i20, RZ;
--:-:-:-:1 @!P1 MOV i21, RZ;
--:-:-:-:1 @!P2 MOV i22, RZ;
--:-:-:-:1 @!P3 MOV i23, RZ;
--:-:-:-:1 @!P4 MOV i24, RZ;
--:-:-:-:1 @!P5 MOV i25, RZ;
--:-:-:-:1  @P0 LDG.E.CI.[+ dtype() +] i20, [track + [+ dsize() +]x<2*$W*$N + 0*$N>];
--:-:-:-:1  @P1 LDG.E.CI.[+ dtype() +] i21, [track + [+ dsize() +]x<2*$W*$N + 1*$N>];
--:-:-:-:1  @P2 LDG.E.CI.[+ dtype() +] i22, [track + [+ dsize() +]x<2*$W*$N + 2*$N>];
--:-:-:-:1  @P3 LDG.E.CI.[+ dtype() +] i23, [track + [+ dsize() +]x<2*$W*$N + 3*$N>];
--:-:-:-:1  @P4 LDG.E.CI.[+ dtype() +] i24, [track + [+ dsize() +]x<2*$W*$N + 4*$N>];
--:-:3:-:1  @P5 LDG.E.CI.[+ dtype() +] i25, [track + [+ dsize() +]x<2*$W*$N + 5*$N>];

--:-:-:-:1 @!P6 R2P PR, pred30, 0x3f;
--:-:-:-:1  @P6 R2P PR,     RZ, 0x3f;
--:-:-:-:1 @!P6 SHF.R.U64 pred30, pred30, 6, pred30;
--:-:-:-:1 @!P0 MOV i30, RZ;
--:-:-:-:1 @!P1 MOV i31, RZ;
--:-:-:-:1 @!P2 MOV i32, RZ;
--:-:-:-:1 @!P3 MOV i33, RZ;
--:-:-:-:1 @!P4 MOV i34, RZ;
--:-:-:-:1 @!P5 MOV i35, RZ;
--:-:-:-:1  @P0 LDG.E.CI.[+ dtype() +] i30, [track + [+ dsize() +]x<3*$W*$N + 0*$N>];
--:-:-:-:1  @P1 LDG.E.CI.[+ dtype() +] i31, [track + [+ dsize() +]x<3*$W*$N + 1*$N>];
--:-:-:-:1  @P2 LDG.E.CI.[+ dtype() +] i32, [track + [+ dsize() +]x<3*$W*$N + 2*$N>];
--:-:-:-:1  @P3 LDG.E.CI.[+ dtype() +] i33, [track + [+ dsize() +]x<3*$W*$N + 3*$N>];
--:-:-:-:1  @P4 LDG.E.CI.[+ dtype() +] i34, [track + [+ dsize() +]x<3*$W*$N + 4*$N>];
--:-:4:-:1  @P5 LDG.E.CI.[+ dtype() +] i35, [track + [+ dsize() +]x<3*$W*$N + 5*$N>];

--:-:-:-:1 @!P6 R2P PR, pred30, 0x3f;
--:-:-:-:1  @P6 R2P PR,     RZ, 0x3f;
--:-:-:-:1 @!P6 SHF.L.U64 pred30, pred30, 24, pred30;
--:-:-:-:1 @!P0 MOV i40, RZ;
--:-:-:-:1 @!P1 MOV i41, RZ;
--:-:-:-:1 @!P2 MOV i42, RZ;
--:-:-:-:1 @!P3 MOV i43, RZ;
--:-:-:-:1 @!P4 MOV i44, RZ;
--:-:-:-:1 @!P5 MOV i45, RZ;
--:-:-:-:1  @P0 LDG.E.CI.[+ dtype() +] i40, [track + [+ dsize() +]x<4*$W*$N + 0*$N>];
--:-:-:-:1  @P1 LDG.E.CI.[+ dtype() +] i41, [track + [+ dsize() +]x<4*$W*$N + 1*$N>];
--:-:-:-:1  @P2 LDG.E.CI.[+ dtype() +] i42, [track + [+ dsize() +]x<4*$W*$N + 2*$N>];
--:-:-:-:1  @P3 LDG.E.CI.[+ dtype() +] i43, [track + [+ dsize() +]x<4*$W*$N + 3*$N>];
--:-:-:-:1  @P4 LDG.E.CI.[+ dtype() +] i44, [track + [+ dsize() +]x<4*$W*$N + 4*$N>];
--:-:5:-:1  @P5 LDG.E.CI.[+ dtype() +] i45, [track + [+ dsize() +]x<4*$W*$N + 5*$N>];

--:-:-:-:1 @!P6 R2P PR, pred36, 0x3f;
--:-:-:-:1  @P6 R2P PR,     RZ, 0x3f;
--:-:-:-:1 @!P0 MOV i50, RZ;
--:-:-:-:1 @!P1 MOV i51, RZ;
--:-:-:-:1 @!P2 MOV i52, RZ;
--:-:-:-:1 @!P3 MOV i53, RZ;
--:-:-:-:1 @!P4 MOV i54, RZ;
--:-:-:-:1 @!P5 MOV i55, RZ;
--:-:-:-:1  @P0 LDG.E.CI.[+ dtype() +] i50, [track + [+ dsize() +]x<5*$W*$N + 0*$N>];
--:-:-:-:1  @P1 LDG.E.CI.[+ dtype() +] i51, [track + [+ dsize() +]x<5*$W*$N + 1*$N>];
--:-:-:-:1  @P2 LDG.E.CI.[+ dtype() +] i52, [track + [+ dsize() +]x<5*$W*$N + 2*$N>];
--:-:-:-:1  @P3 LDG.E.CI.[+ dtype() +] i53, [track + [+ dsize() +]x<5*$W*$N + 3*$N>];
--:-:-:-:1  @P4 LDG.E.CI.[+ dtype() +] i54, [track + [+ dsize() +]x<5*$W*$N + 4*$N>];
--:-:6:-:1  @P5 LDG.E.CI.[+ dtype() +] i55, [track + [+ dsize() +]x<5*$W*$N + 5*$N>];

</SCHEDULE_BLOCK>

--:-:-:-:5      BAR.SYNC 0;

3f:-:-:-:5      IADD   track0.CC, track0, -partialC;
--:-:-:-:1      IADD   writeS,    writeS, 4x<32*36*2*2>;
--:-:-:-:0      IADD.X track1,    track1, -RZ;

--:-:-:-:5      BRA.U IMAGE_LOOP;

##############################################################
FILTER_SETUP:

<SCHEDULE_BLOCK>
// writeS += 32*36*2*4
--:-:-:-:1      IADD writeS, writeS, 4x<32*36*2>;

--:-:-:-:1      MOV swapBuf, 4x<32*36*2*2>;

// P6 = c == partialC == 1
--:-:-:-:1      ISETP.EQ.AND P6, PT, c, 1, PT;
--:-:-:-:1      ISETP.EQ.AND P6, PT, c, partialC, P6;
--:-:-:-:1      XMAD     partC,    partialC, param_RSK, RZ;
--:-:-:-:1      XMAD.PSL partialC, partialC, param_RSK.H1, partC;
--:-:-:-:1      SHL  partialC, partialC, [+ dshift() +];

// k = idx_K*32 + tid & 31
--:-:-:-:1      ISCADD  kk, idx_K, tid31,  5;
--:-:-:-:1      ISETP.LT.AND P6, PT, kk, param_K, !P6;
--:-:-:-:1      ISETP.LT.AND P2, PT, kk, param_K, PT;

// a0 = c*RSK + k
--:-:-:-:1      XMAD.LO2C offset, c, param_RSK, kk;
--:-:-:-:1      LEA      track0.CC, offset, param_F[0],     [+ dshift() +];
--:-:-:-:1      LEA.HI.X track1,    offset, param_F[1], RZ, [+ dshift() +];

--:-:-:-:1      STS [writeS + 4x<32*0>], RZ;
--:-:-:-:1      STS [writeS + 4x<32*1>], RZ;
--:-:-:-:1      STS [writeS + 4x<32*2>], RZ;
--:-:-:-:1      STS [writeS + 4x<32*3>], RZ;

20:-:-:-:1 @!P6 MOV f00, RZ;
--:-:-:-:1 @!P6 MOV f01, RZ;
--:-:-:-:1 @!P6 MOV f02, RZ;
--:-:-:-:1  @P6 LDG.E.CI.[+ dtype() +] f00, [track + [+ dsize() +]x<0*3*$K + 0*$K>];
--:-:-:-:1  @P6 LDG.E.CI.[+ dtype() +] f01, [track + [+ dsize() +]x<0*3*$K + 1*$K>];
--:-:1:-:1  @P6 LDG.E.CI.[+ dtype() +] f02, [track + [+ dsize() +]x<0*3*$K + 2*$K>];

--:-:-:-:1 @!P6 MOV f10, RZ;
--:-:-:-:1 @!P6 MOV f11, RZ;
--:-:-:-:1 @!P6 MOV f12, RZ;
--:-:-:-:1  @P6 LDG.E.CI.[+ dtype() +] f10, [track + [+ dsize() +]x<1*3*$K + 0*$K>];
--:-:-:-:1  @P6 LDG.E.CI.[+ dtype() +] f11, [track + [+ dsize() +]x<1*3*$K + 1*$K>];
--:-:2:-:1  @P6 LDG.E.CI.[+ dtype() +] f12, [track + [+ dsize() +]x<1*3*$K + 2*$K>];

--:-:-:-:1 @!P6 MOV f20, RZ;
--:-:-:-:1 @!P6 MOV f21, RZ;
--:-:-:-:1 @!P6 MOV f22, RZ;
--:-:-:-:1  @P6 LDG.E.CI.[+ dtype() +] f20, [track + [+ dsize() +]x<2*3*$K + 0*$K>];
--:-:-:-:1  @P6 LDG.E.CI.[+ dtype() +] f21, [track + [+ dsize() +]x<2*3*$K + 1*$K>];
--:5:3:-:1  @P6 LDG.E.CI.[+ dtype() +] f22, [track + [+ dsize() +]x<2*3*$K + 2*$K>];

</SCHEDULE_BLOCK>

--:-:-:-:5      BAR.SYNC 0;

10:-:-:-:4      IADD   track0.CC, track0, -partialC;
--:-:-:-:1      IADD   writeS, writeS, swapBuf;
--:-:-:-:1      IADD   swapBuf, RZ, -swapBuf;
--:-:-:-:0      IADD.X track1,    track1, -RZ;

--:-:-:-:5      BRA.U FILTER_LOOP;

##############################################################

COMPUTE_SETUP:

<SCHEDULE_BLOCK>
--:-:-:-:1      MOV swapBuf, 4x<32*36*2*2>;

[+ join '', map sprintf("--:-:-:-:1      LDS.U.128 czero%02d, [addr_zero];\n", $_ * 4), 0..15; +]

--:-:-:-:1      IADD tid128, tid, -128;

// readIs = ((tid & -16) >> 1) | ((tid >> 1) & 3)
// readFs = ((tid & -16) >> 1) | ((tid &  8) >> 2) | (tid & 1)
--:-:-:-:1      LOP.AND  tid16,  tid128, -16;
--:-:-:-:1      SHR.U32  tid16,  tid16,   1;

--:-:-:-:1      BFE.U32  readIs, tid128, 0x201; // 2 bits at position 1
--:-:-:-:1      LOP.OR   readIs, readIs, tid16;
--:-:-:-:1      ISCADD   readIs, readIs, 4x<32*4 + 32*36*2*2>, 4;

--:-:-:-:1      LOP.AND  tid_1,  tid128, 1;
--:-:-:-:1      LOP.AND  readFs, tid128, 8;
--:-:-:-:1      SHR.U32  readFs, readFs, 2;
--:-:-:-:1      IADD3    readFs, readFs, tid16, tid_1;
--:-:-:-:0      ISCADD   readFs, readFs, 4x<32*4 + 32*36*2*3>, 4;
</SCHEDULE_BLOCK>

--:-:-:-:5      BAR.SYNC 0;

// Let Load loop run once to transform initial load and store to shared.
--:-:-:-:5      BAR.SYNC 0;

--:-:-:-:1      LDS.U.128 jc0Ix0, [readIs + 4x<0*32*36 + 00>];
--:-:-:-:1      LDS.U.128 jc0Fy0, [readFs + 4x<0*32*36 + 00>];
--:-:-:-:1      LDS.U.128 jc0Ix4, [readIs + 4x<0*32*36 + 16>];
--:-:1:-:2      LDS.U.128 jc0Fy4, [readFs + 4x<0*32*36 + 16>];

COMPUTE_LOOP:
[+
    my %insert = (

        j0c33 => "--:-:-:-:1      ISETP.GT.AND P0, PT, C, 2, PT;\n" .
                 "--:-:-:-:1      IADD C, C, -2;\n",

        j0c62 => "02:-:-:Y:5      BAR.SYNC 0;\n" .
                 "--:-:-:-:1      IADD readFs, readFs, -swapBuf;\n" .
                 "--:-:-:-:1      IADD readIs, readIs, -swapBuf;\n" .
                 "--:-:-:-:1      IADD swapBuf, RZ,    -swapBuf;\n",

        j1c63 => "--:-:-:Y:5  \@P0 BRA.U COMPUTE_LOOP;\n" .
                 "--:-:-:Y:5      BRA.U COMPUTE_FINISH;\n",
    );
    my @cOrder;
    my @swirl = ([0,2],[1,2],[1,0],[0,0]);
    my @y = (0,1,4,5);
    foreach my $x (0,2,4,6)
    {
        foreach my $y (@y)
        {
            push @cOrder, [$x + $_->[0], $y + $_->[1]] foreach @swirl;
        }
        @y = reverse @y;
    }
    my $out;
    foreach my $j (0 .. 1)
    {
        my $odd    = $j;
        my $nOdd   = 1 - $j;
        my $rsPred = $j == 1 ? '@P0' : '   ';
        my $bar    = $j == 0 ? '2' : '-';

        $insert{"j${j}c0"}  = sprintf "--:-:-:-:1  %s LDS.U.128 jc%dFy4, [readFs + 4x<%d*32*36 + 16>];\n", $rsPred, $nOdd, $nOdd;
        $insert{"j${j}c2"}  = sprintf "--:-:-:-:1  %s LDS.U.128 jc%dIx4, [readIs + 4x<%d*32*36 + 16>];\n", $rsPred, $nOdd, $nOdd;
        $insert{"j${j}c4"}  = sprintf "--:-:-:-:1  %s LDS.U.128 jc%dFy0, [readFs + 4x<%d*32*36 + 00>];\n", $rsPred, $nOdd, $nOdd;

        $insert{"j${j}c31"} = sprintf "--:%s:1:-:1  %s LDS.U.128 jc%dIx0, [readIs + 4x<%d*32*36 + 00>];\n", $bar, $rsPred, $nOdd, $nOdd;


        foreach my $c (0 .. 63)
        {
            my ($x,$y) = @{$cOrder[$c]};

            my $ins    = $insert{"j${j}c$c"} || '';

            my $stall  = $ins =~ /^[^\n]*(?:LDS|I2I|I2F|F2I|F2F|LDG|STS|BAR|BRA)/ ? 0 : 1;

            #$stall = '4' if $stall && $c % 2 == 0 && $j == 0 && $c > 16;

            my $yield  = $c % 5 == 0 && $stall ? 'Y' : '-';

            my $wait   = $c == 0 ? '01' : '--';

            my $ctrl   = "$wait:-:-:-:$stall";

            $out .= sprintf "%s      FFMA ccx%dy%d, jc%dIx%d, jc%dFy%d, ccx%dy%d;\n%s", $ctrl,  $x,$y,  $odd,$x,  $odd,$y,  $x,$y,  $ins;
        }
    }
    return $out;
+]

IMAGE_LOOP:

[+
    our $convert_in; return $convert_in ? q{
01:-:-:-:1      F2F.F32.F16 i00, i00;
--:-:-:-:1      F2F.F32.F16 i01, i01;
--:-:-:-:1      F2F.F32.F16 i02, i02;
--:-:-:-:1      F2F.F32.F16 i03, i03;
--:-:-:-:1      F2F.F32.F16 i04, i04;
--:-:1:-:1      F2F.F32.F16 i05, i05;

02:-:-:-:1      F2F.F32.F16 i10, i10;
--:-:-:-:1      F2F.F32.F16 i11, i11;
--:-:-:-:1      F2F.F32.F16 i12, i12;
--:-:-:-:1      F2F.F32.F16 i13, i13;
--:-:-:-:1      F2F.F32.F16 i14, i14;
--:-:2:-:1      F2F.F32.F16 i15, i15;

04:-:-:-:1      F2F.F32.F16 i20, i20;
--:-:-:-:1      F2F.F32.F16 i21, i21;
--:-:-:-:1      F2F.F32.F16 i22, i22;
--:-:-:-:1      F2F.F32.F16 i23, i23;
--:-:-:-:1      F2F.F32.F16 i24, i24;
--:-:3:-:1      F2F.F32.F16 i25, i25;

08:-:-:-:1      F2F.F32.F16 i30, i30;
--:-:-:-:1      F2F.F32.F16 i31, i31;
--:-:-:-:1      F2F.F32.F16 i32, i32;
--:-:-:-:1      F2F.F32.F16 i33, i33;
--:-:-:-:1      F2F.F32.F16 i34, i34;
--:-:4:-:1      F2F.F32.F16 i35, i35;

10:-:-:-:1      F2F.F32.F16 i40, i40;
--:-:-:-:1      F2F.F32.F16 i41, i41;
--:-:-:-:1      F2F.F32.F16 i42, i42;
--:-:-:-:1      F2F.F32.F16 i43, i43;
--:-:-:-:1      F2F.F32.F16 i44, i44;
--:-:5:-:1      F2F.F32.F16 i45, i45;

20:-:-:-:1      F2F.F32.F16 i50, i50;
--:-:-:-:1      F2F.F32.F16 i51, i51;
--:-:-:-:1      F2F.F32.F16 i52, i52;
--:-:-:-:1      F2F.F32.F16 i53, i53;
--:-:-:-:1      F2F.F32.F16 i54, i54;
--:-:6:-:2      F2F.F32.F16 i55, i55;
        } : '';
+]
<SCHEDULE_BLOCK>
[+
    my $out;
    foreach my $i (0 .. 5)
    {
        my $w = $i == 0 ? '3f' : '--';
        $out .= qq{
$w:-:-:-:1      FFMA ti4,   i2$i, -2.640625,   i4$i;
--:-:-:-:1      FFMA ti5,   i3$i, -2.640625,   i5$i;
--:-:-:-:1      FFMA ti0,   i2$i, -2.25,       i4$i;
--:-:-:-:1      FFMA ti1,   i1$i, -2.25,       i3$i;
--:-:-:-:1      FFMA ti2,   i2$i, -0.390625,   i4$i;
--:-:-:-:1      FFMA ti3,   i1$i, -0.390625,   i3$i;
--:-:-:-:1      FFMA TI0$i, i0$i,  0.87890625, ti4;
--:-:-:-:1      FFMA TI5$i, i1$i,  0.87890625, ti5;
--:-:-:-:1      FFMA TI1$i, ti1,   0.625,      ti0;
--:-:-:-:1      FFMA TI2$i, ti1,  -0.625,      ti0;
--:-:-:-:1      FFMA TI3$i, ti3,   1.5,        ti2;
--:-:-:-:1      FFMA TI4$i, ti3,  -1.5,        ti2;
        };
    }
    return $out;
+]

--:-:-:-:1      LDS.U.128 jl0Fy4, [readFs + 4x<0*32*36 + 16>];
--:-:-:-:1      LDS.U.128 jl0Ix0, [readIs + 4x<0*32*36 + 00>];
--:-:-:-:1      LDS.U.128 jl0Fy0, [readFs + 4x<0*32*36 + 00>];

--:-:-:-:1      ISETP.GT.AND P0, PT, C, 2, PT;

--:-:-:-:1      IADD   track0.CC, track0, param_YXN2p;
--:-:-:-:1      IADD.X track1,    track1, RZ;

//--:-:-:-:1      LOP32I.AND pred30, pred30, 0xffffff;
--:-:-:-:1 @!P0 BFI pred36, RZ, 0x600, pred36;
--:-:-:-:1 @!P0 MOV pred30, RZ;

--:-:-:-:1      R2P PR, pred30, 0x3f;
--:-:-:-:1      SHF.R.U64 pred30, pred30, 6, pred30;

[+
    my $out;
    foreach my $i (0 .. 5)
    {
        $out .= qq{
--:-:-:-:1      FFMA ti4,    TI${i}2, -2.640625,   TI${i}4;
--:-:-:-:1      FFMA ti5,    TI${i}3, -2.640625,   TI${i}5;
--:-:-:-:1      FFMA ti0,    TI${i}2, -2.25,       TI${i}4;
--:-:-:-:1      FFMA ti1,    TI${i}1, -2.25,       TI${i}3;
--:-:-:-:1      FFMA ti2,    TI${i}2, -0.390625,   TI${i}4;
--:-:-:-:1      FFMA ti3,    TI${i}1, -0.390625,   TI${i}3;
--:-:-:-:1      FFMA I${i}0, TI${i}0,  0.87890625, ti4;
--:-:-:-:1      FFMA I${i}5, TI${i}1,  0.87890625, ti5;
--:-:-:-:1      FFMA I${i}1, ti1,      0.625,      ti0;
--:-:-:-:1      FFMA I${i}2, ti1,     -0.625,      ti0;
--:-:-:-:1      FFMA I${i}3, ti3,      1.5,        ti2;
--:-:-:-:1      FFMA I${i}4, ti3,     -1.5,        ti2;
        };
    }
    return $out;
+]
<ORDERED>
--:-:-:-:1      STS [writeS + 4x<32*(0*6 + 3)>], I03;
--:-:-:-:1      STS [writeS + 4x<32*(0*6 + 4)>], I04;
--:-:-:-:1      STS [writeS + 4x<32*(0*6 + 0)>], I00;
--:-:-:-:1      STS [writeS + 4x<32*(0*6 + 5)>], I05;
--:-:-:-:1      STS [writeS + 4x<32*(0*6 + 1)>], I01;
--:1:-:-:1      STS [writeS + 4x<32*(0*6 + 2)>], I02;


--:-:-:-:1      STS [writeS + 4x<32*(1*6 + 0)>], I10;
--:-:-:-:1      STS [writeS + 4x<32*(1*6 + 5)>], I15;
--:-:-:-:1      STS [writeS + 4x<32*(1*6 + 3)>], I13;
--:-:-:-:1      STS [writeS + 4x<32*(1*6 + 1)>], I11;
--:-:-:-:1      STS [writeS + 4x<32*(1*6 + 2)>], I12;
--:2:-:-:1      STS [writeS + 4x<32*(1*6 + 4)>], I14;

01:-:-:-:1  @P0 LDG.E.CI.[+ dtype() +] i00, [track + [+ dsize() +]x<0*$W*$N + 0*$N>];
--:-:-:-:1  @P1 LDG.E.CI.[+ dtype() +] i01, [track + [+ dsize() +]x<0*$W*$N + 1*$N>];
--:-:-:-:1  @P2 LDG.E.CI.[+ dtype() +] i02, [track + [+ dsize() +]x<0*$W*$N + 2*$N>];
--:-:-:-:1  @P3 LDG.E.CI.[+ dtype() +] i03, [track + [+ dsize() +]x<0*$W*$N + 3*$N>];
--:-:-:-:1  @P4 LDG.E.CI.[+ dtype() +] i04, [track + [+ dsize() +]x<0*$W*$N + 4*$N>];
--:-:1:-:1  @P5 LDG.E.CI.[+ dtype() +] i05, [track + [+ dsize() +]x<0*$W*$N + 5*$N>];
--:-:-:-:1 @!P0 I2I.U32.U32 i00, RZ;
--:-:-:-:1 @!P1 I2I.U32.U32 i01, RZ;
--:-:-:-:1 @!P2 I2I.U32.U32 i02, RZ;
--:-:-:-:1 @!P3 I2I.U32.U32 i03, RZ;
--:-:-:-:1 @!P4 I2I.U32.U32 i04, RZ;
--:-:-:-:1 @!P5 I2I.U32.U32 i05, RZ;
--:-:-:-:1      R2P PR, pred30, 0x3f;

--:-:-:-:1      STS [writeS + 4x<32*(2*6 + 0)>], I20;
--:-:-:-:1      STS [writeS + 4x<32*(2*6 + 5)>], I25;
--:-:-:-:1      STS [writeS + 4x<32*(2*6 + 1)>], I21;
--:-:-:-:1      STS [writeS + 4x<32*(2*6 + 2)>], I22;
--:-:-:-:1      STS [writeS + 4x<32*(2*6 + 3)>], I23;
--:-:-:-:1      SHF.R.U64 pred30, pred30, 6, pred30;
--:3:-:-:1      STS [writeS + 4x<32*(2*6 + 4)>], I24;

--:-:-:-:1      STS [writeS + 4x<32*(3*6 + 0)>], I30;
--:-:-:-:1      STS [writeS + 4x<32*(3*6 + 5)>], I35;
--:-:-:-:1      STS [writeS + 4x<32*(3*6 + 1)>], I31;
--:-:-:-:1      STS [writeS + 4x<32*(3*6 + 2)>], I32;
--:-:-:-:1      STS [writeS + 4x<32*(3*6 + 3)>], I33;
--:4:-:-:1      STS [writeS + 4x<32*(3*6 + 4)>], I34;

02:-:-:-:1  @P0 LDG.E.CI.[+ dtype() +] i10, [track + [+ dsize() +]x<1*$W*$N + 0*$N>];
--:-:-:-:1  @P1 LDG.E.CI.[+ dtype() +] i11, [track + [+ dsize() +]x<1*$W*$N + 1*$N>];
--:-:-:-:1  @P2 LDG.E.CI.[+ dtype() +] i12, [track + [+ dsize() +]x<1*$W*$N + 2*$N>];
--:-:-:-:1  @P3 LDG.E.CI.[+ dtype() +] i13, [track + [+ dsize() +]x<1*$W*$N + 3*$N>];
--:-:-:-:1  @P4 LDG.E.CI.[+ dtype() +] i14, [track + [+ dsize() +]x<1*$W*$N + 4*$N>];
--:-:2:-:1  @P5 LDG.E.CI.[+ dtype() +] i15, [track + [+ dsize() +]x<1*$W*$N + 5*$N>];
--:-:-:-:1 @!P0 I2I.U32.U32 i10, RZ;
--:-:-:-:1 @!P1 I2I.U32.U32 i11, RZ;
--:-:-:-:1 @!P2 I2I.U32.U32 i12, RZ;
--:-:-:-:1 @!P3 I2I.U32.U32 i13, RZ;
--:-:-:-:1 @!P4 I2I.U32.U32 i14, RZ;
--:-:-:-:1 @!P5 I2I.U32.U32 i15, RZ;

--:-:-:-:5      R2P PR, pred30, 0x3f; // FORCE

--:-:-:-:1      STS [writeS + 4x<32*(4*6 + 0)>], I40;
--:-:-:-:1      STS [writeS + 4x<32*(4*6 + 5)>], I45;
--:-:-:-:1      STS [writeS + 4x<32*(4*6 + 1)>], I41;
--:-:-:-:1      STS [writeS + 4x<32*(4*6 + 2)>], I42;
</ORDERED>
</SCHEDULE_BLOCK>

<SCHEDULE_BLOCK>
<ORDERED>
--:-:-:-:1      STS [writeS + 4x<32*(4*6 + 3)>], I43;
--:-:-:-:1      STS [writeS + 4x<32*(4*6 + 4)>], I44;
--:-:-:-:1      SHF.R.U64 pred30, pred30, 6, pred30;

--:-:-:-:1      LDS.U.128 jl1Fy4, [readFs + 4x<1*32*36 + 16>];
--:-:-:-:1      LDS.U.128 jl1Ix0, [readIs + 4x<1*32*36 + 00>];

04:-:-:-:1  @P0 LDG.E.CI.[+ dtype() +] i20, [track + [+ dsize() +]x<2*$W*$N + 0*$N>];
--:-:-:-:1  @P1 LDG.E.CI.[+ dtype() +] i21, [track + [+ dsize() +]x<2*$W*$N + 1*$N>];
--:-:-:-:1  @P2 LDG.E.CI.[+ dtype() +] i22, [track + [+ dsize() +]x<2*$W*$N + 2*$N>];
--:-:-:-:1  @P3 LDG.E.CI.[+ dtype() +] i23, [track + [+ dsize() +]x<2*$W*$N + 3*$N>];
--:-:-:-:1  @P4 LDG.E.CI.[+ dtype() +] i24, [track + [+ dsize() +]x<2*$W*$N + 4*$N>];
--:-:3:-:1  @P5 LDG.E.CI.[+ dtype() +] i25, [track + [+ dsize() +]x<2*$W*$N + 5*$N>];
--:-:-:-:1 @!P0 I2I.U32.U32 i20, RZ;
--:-:-:-:1 @!P1 I2I.U32.U32 i21, RZ;
--:-:-:-:1 @!P2 I2I.U32.U32 i22, RZ;
--:-:-:-:1 @!P3 I2I.U32.U32 i23, RZ;
--:-:-:-:1 @!P4 I2I.U32.U32 i24, RZ;
--:-:-:-:1 @!P5 I2I.U32.U32 i25, RZ;
--:-:-:-:6      R2P PR, pred30, 0x3f; // FORCE

--:-:-:-:1      SHF.R.U64 pred30, pred30, 6, pred30;
--:-:-:-:1      STS [writeS + 4x<32*(5*6 + 0)>], I50;
--:-:-:-:1      STS [writeS + 4x<32*(5*6 + 5)>], I55;
--:-:-:-:1      STS [writeS + 4x<32*(5*6 + 1)>], I51;
--:-:-:-:1      STS [writeS + 4x<32*(5*6 + 2)>], I52;
--:-:-:-:1      STS [writeS + 4x<32*(5*6 + 3)>], I53;
--:6:-:-:1      STS [writeS + 4x<32*(5*6 + 4)>], I54;

08:-:-:-:1  @P0 LDG.E.CI.[+ dtype() +] i30, [track + [+ dsize() +]x<3*$W*$N + 0*$N>];
--:-:-:-:1  @P1 LDG.E.CI.[+ dtype() +] i31, [track + [+ dsize() +]x<3*$W*$N + 1*$N>];
--:-:-:-:1  @P2 LDG.E.CI.[+ dtype() +] i32, [track + [+ dsize() +]x<3*$W*$N + 2*$N>];
--:-:-:-:1  @P3 LDG.E.CI.[+ dtype() +] i33, [track + [+ dsize() +]x<3*$W*$N + 3*$N>];
--:-:-:-:1  @P4 LDG.E.CI.[+ dtype() +] i34, [track + [+ dsize() +]x<3*$W*$N + 4*$N>];
--:-:4:-:1  @P5 LDG.E.CI.[+ dtype() +] i35, [track + [+ dsize() +]x<3*$W*$N + 5*$N>];
--:-:-:-:1 @!P0 I2I.U32.U32 i30, RZ;
--:-:-:-:1 @!P1 I2I.U32.U32 i31, RZ;
--:-:-:-:1 @!P2 I2I.U32.U32 i32, RZ;
--:-:-:-:1 @!P3 I2I.U32.U32 i33, RZ;
--:-:-:-:1 @!P4 I2I.U32.U32 i34, RZ;
--:-:-:-:1 @!P5 I2I.U32.U32 i35, RZ;
--:-:-:-:c      R2P PR, pred30, 0x3f; // FORCE

--:-:-:-:1  @P0 LDG.E.CI.[+ dtype() +] i40, [track + [+ dsize() +]x<4*$W*$N + 0*$N>];
--:-:-:-:1  @P1 LDG.E.CI.[+ dtype() +] i41, [track + [+ dsize() +]x<4*$W*$N + 1*$N>];
--:-:-:-:1  @P2 LDG.E.CI.[+ dtype() +] i42, [track + [+ dsize() +]x<4*$W*$N + 2*$N>];
--:-:-:-:1  @P3 LDG.E.CI.[+ dtype() +] i43, [track + [+ dsize() +]x<4*$W*$N + 3*$N>];
--:-:-:-:1  @P4 LDG.E.CI.[+ dtype() +] i44, [track + [+ dsize() +]x<4*$W*$N + 4*$N>];
--:-:5:-:1  @P5 LDG.E.CI.[+ dtype() +] i45, [track + [+ dsize() +]x<4*$W*$N + 5*$N>];
--:-:-:-:1      SHF.L.U64 pred30, pred30, 24, pred30;

--:-:-:-:1 @!P0 I2I.U32.U32 i40, RZ;
--:-:-:-:1 @!P1 I2I.U32.U32 i41, RZ;
--:-:-:-:1 @!P2 I2I.U32.U32 i42, RZ;
--:-:-:-:1 @!P3 I2I.U32.U32 i43, RZ;
--:-:-:-:1 @!P4 I2I.U32.U32 i44, RZ;
--:-:-:-:1 @!P5 I2I.U32.U32 i45, RZ;
--:-:-:-:a      R2P PR, pred36, 0x3f; // FORCE

20:-:-:-:1  @P0 LDG.E.CI.[+ dtype() +] i50, [track + [+ dsize() +]x<5*$W*$N + 0*$N>];
--:-:-:-:1 @!P0 I2I.U32.U32 i50, RZ;
--:-:-:-:1  @P1 LDG.E.CI.[+ dtype() +] i51, [track + [+ dsize() +]x<5*$W*$N + 1*$N>];
--:-:-:-:1  @P2 LDG.E.CI.[+ dtype() +] i52, [track + [+ dsize() +]x<5*$W*$N + 2*$N>];
--:-:-:-:1  @P3 LDG.E.CI.[+ dtype() +] i53, [track + [+ dsize() +]x<5*$W*$N + 3*$N>];
--:-:-:-:1  @P4 LDG.E.CI.[+ dtype() +] i54, [track + [+ dsize() +]x<5*$W*$N + 4*$N>];
--:-:6:-:1  @P5 LDG.E.CI.[+ dtype() +] i55, [track + [+ dsize() +]x<5*$W*$N + 5*$N>];
--:-:-:-:1 @!P1 I2I.U32.U32 i51, RZ;
--:-:-:-:1 @!P2 I2I.U32.U32 i52, RZ;
--:-:-:-:1 @!P3 I2I.U32.U32 i53, RZ;
--:-:-:-:1 @!P4 I2I.U32.U32 i54, RZ;
--:-:-:-:1 @!P5 I2I.U32.U32 i55, RZ;
</ORDERED>

<ORDERED>
[+
    our ($vsize, $dsize, $convert_in);
    my %insert = (
        j0c15 => "--:-:5:-:1      LDS.U.128 jl1Fy0, [readFs + 4x<1*32*36 + 00>];\n",
    );

    my @cOrder;
    my @swirl = ([0,2],[1,2],[1,0],[0,0]);
    foreach my $xy ([0,0],[0,1],[2,1],[2,0],[2,4],[2,5],[0,5],[0,4])
    {
        my ($x, $y) = @$xy;
        push @cOrder, [$x + $_->[0], $y + $_->[1]] foreach @swirl;
    }
    my $out;
    foreach my $j (0 .. 1)
    {
        foreach my $c (0 .. 31)
        {
            my ($x,$y) = @{$cOrder[$c]};

            my $ins    = $insert{"j${j}c$c"} || '';

            my $wait   = $c == 0 && $j == 1 ? "10" : '--';

            my $ctrl   = "$wait:-:-:-:1";

            $out .= sprintf "%s      FFMA clx%dy%d, jl%dIx%d, jl%dFy%d, clx%dy%d;\n%s", $ctrl,  $x,$y,  $j,$x,  $j,$y,  $x,$y,  $ins;
        }
    }
    return $out;
+]
</ORDERED>
--:-:-:-:1      LOP.AND.Z P0, RZ, pred36, 0x100;
--:-:-:-:1      LOP.XOR pred36, pred36, 0x100;

--:-:-:-:1      ISETP.GT.AND P1, PT, C, 0, PT;

--:-:-:-:1  @P0 MOV32I swapBuff,  4x<32*36*2*2>;

</SCHEDULE_BLOCK>
--:-:-:-:1 @!P0 MOV32I swapBuff, -4x<32*36*2*2>;
--:-:-:-:0      IADD C, C, -2;
--:-:-:Y:5      BAR.SYNC 0;
--:-:-:-:1      IADD readFs, readFs,  swapBuff;
--:-:-:-:1      IADD readIs, readIs,  swapBuff;
--:-:-:-:1      IADD writeS, writeS, -swapBuff;
--:-:-:Y:5  @P1 BRA.U IMAGE_LOOP;
--:-:-:Y:5      BRA.U LOAD_FINISH;

FILTER_LOOP:

[+
    our $convert_in; return $convert_in ? q{
01:-:-:-:1      F2F.F32.F16 f00, f00;
--:-:-:-:1      F2F.F32.F16 f01, f01;
--:-:1:-:1      F2F.F32.F16 f02, f02;

02:-:-:-:1      F2F.F32.F16 f10, f10;
--:-:-:-:1      F2F.F32.F16 f11, f11;
--:-:2:-:1      F2F.F32.F16 f12, f12;

04:-:-:-:1      F2F.F32.F16 f20, f20;
--:-:-:-:1      F2F.F32.F16 f21, f21;
--:-:3:-:1      F2F.F32.F16 f22, f22;
        } : '';
+]
<SCHEDULE_BLOCK>
--:-:-:-:1      MOV32I rcp6,  0.688403361344538;
--:-:-:-:1      MOV32I rcp8,  0.430252100840336;
--:-:-:-:1      MOV32I rcp24, 0.119514472455649;
--:-:-:-:1      MOV32I rcp12, 0.179271708683473;
07:-:-:-:1      FMUL32I tf00, f20, 0.26890756302521;
--:-:-:-:1      FMUL32I tf01, f21, 0.26890756302521;
--:-:-:-:1      FMUL32I tf02, f22, 0.26890756302521;
--:-:-:-:1      FFMA tf10, f00, -rcp6, -tf00;
--:-:-:-:1      FFMA tf20, f00,  rcp24, tf00;
--:-:-:-:1      FFMA tf11, f01, -rcp6, -tf01;
--:-:-:-:1      FFMA tf21, f01,  rcp24, tf01;
--:-:-:-:1      FFMA tf12, f02, -rcp6, -tf02;
--:-:-:-:1      FFMA tf22, f02,  rcp24, tf02;

--:-:-:-:1      FMUL32I TF00, f00,  1.13777777777778;
--:-:-:-:1      FFMA TF10, f10, -rcp8,  tf10;
--:-:-:-:1      FFMA TF20, f10,  rcp8,  tf10;
--:-:-:-:1      FFMA TF30, f10,  rcp12, tf20;
--:-:-:-:1      FFMA TF40, f10, -rcp12, tf20;
//--:-:-:-:1      MOV  TF50, f20;

--:-:-:-:1      FMUL32I TF02, f02,  1.13777777777778;
--:-:-:-:1      FFMA TF12, f12, -rcp8,  tf12;
--:-:-:-:1      FFMA TF22, f12,  rcp8,  tf12;
--:-:-:-:1      FFMA TF32, f12,  rcp12, tf22;
--:-:-:-:1      FFMA TF42, f12, -rcp12, tf22;
//--:-:-:-:1      MOV  TF52, f22;

--:-:-:-:1      FMUL32I TF01, f01,  1.13777777777778;
--:-:-:-:1      FFMA TF11, f11, -rcp8,  tf11;
--:-:-:-:1      FFMA TF21, f11,  rcp8,  tf11;
--:-:-:-:1      FFMA TF31, f11,  rcp12, tf21;
--:-:-:-:1      FFMA TF41, f11, -rcp12, tf21;
//--:-:-:-:1      MOV  TF51, f21;

--:-:-:-:1      FMUL32I ff00, TF02, 0.26890756302521;
--:-:-:-:1      FMUL32I ff10, TF12, 0.26890756302521;
--:-:-:-:1      FMUL32I ff20, TF22, 0.26890756302521;
--:-:-:-:1      FMUL32I ff30, TF32, 0.26890756302521;
--:-:-:-:1      FMUL32I ff40, TF42, 0.26890756302521;
--:-:-:-:1      FMUL32I ff50, TF52, 0.26890756302521;
--:-:-:-:1      FFMA ff01, TF00, -rcp6, -ff00;
--:-:-:-:1      FFMA ff02, TF00,  rcp24, ff00;
--:-:-:-:1      FFMA ff11, TF10, -rcp6, -ff10;
--:-:-:-:1      FFMA ff12, TF10,  rcp24, ff10;
--:-:-:-:1      FFMA ff21, TF20, -rcp6, -ff20;
--:-:-:-:1      FFMA ff22, TF20,  rcp24, ff20;
--:-:-:-:1      FFMA ff31, TF30, -rcp6, -ff30;
--:-:-:-:1      FFMA ff32, TF30,  rcp24, ff30;
--:-:-:-:1      FFMA ff41, TF40, -rcp6, -ff40;
--:-:-:-:1      FFMA ff42, TF40,  rcp24, ff40;
--:-:-:-:1      FFMA ff51, TF50, -rcp6, -ff50;
--:-:-:-:1      FFMA ff52, TF50,  rcp24, ff50;

--:-:-:-:1      FMUL32I F00, TF00,  1.13777777777778;
--:-:-:-:1      FFMA F01, TF01, -rcp8,  ff01;
--:-:-:-:1      FFMA F02, TF01,  rcp8,  ff01;
--:-:-:-:1      FFMA F03, TF01,  rcp12, ff02;
--:-:-:-:1      FFMA F04, TF01, -rcp12, ff02;
//--:-:-:-:1      MOV  F05, TF02;

--:-:-:-:1      FMUL32I F10, TF10,  1.13777777777778;
--:-:-:-:1      FFMA F11, TF11, -rcp8,  ff11;
--:-:-:-:1      FFMA F12, TF11,  rcp8,  ff11;
--:-:-:-:1      FFMA F13, TF11,  rcp12, ff12;
--:-:-:-:1      FFMA F14, TF11, -rcp12, ff12;
//--:-:-:-:1      MOV  F15, TF12;

--:-:-:-:1      FMUL32I F20, TF20,  1.13777777777778;
--:-:-:-:1      FFMA F21, TF21, -rcp8,  ff21;
--:-:-:-:1      FFMA F22, TF21,  rcp8,  ff21;
--:-:-:-:1      FFMA F23, TF21,  rcp12, ff22;
--:-:-:-:1      FFMA F24, TF21, -rcp12, ff22;
//--:-:-:-:1      MOV  F25, TF22;

--:-:-:-:1      FMUL32I F30, TF30,  1.13777777777778;
--:-:-:-:1      FFMA F31, TF31, -rcp8,  ff31;
--:-:-:-:1      FFMA F32, TF31,  rcp8,  ff31;
--:-:-:-:1      FFMA F33, TF31,  rcp12, ff32;
--:-:-:-:1      FFMA F34, TF31, -rcp12, ff32;
//--:-:-:-:1      MOV  F35, TF32;

--:-:-:-:1      FMUL32I F40, TF40,  1.13777777777778;
--:-:-:-:1      FFMA F41, TF41, -rcp8,  ff41;
--:-:-:-:1      FFMA F42, TF41,  rcp8,  ff41;
--:-:-:-:1      FFMA F43, TF41,  rcp12, ff42;
--:-:-:-:1      FFMA F44, TF41, -rcp12, ff42;
//--:-:-:-:1      MOV  F45, TF42;

--:-:-:-:1      FMUL32I F50, TF50,  1.13777777777778;
--:-:-:-:1      FFMA F51, TF51, -rcp8,  ff51;
--:-:-:-:1      FFMA F52, TF51,  rcp8,  ff51;
--:-:-:-:1      FFMA F53, TF51,  rcp12, ff52;
--:-:-:-:1      FFMA F54, TF51, -rcp12, ff52;
//--:-:-:-:1      MOV  F55, TF52;

--:-:-:-:1      ISETP.GT.AND P0, PT, C, 2, P2;
--:-:-:-:1      ISETP.GT.AND P1, PT, C, 0, PT;
--:-:-:-:1      IADD C, C, -2;

--:-:-:-:1      LDS.U.128 jl0Fy4, [readFs + 4x<0*32*36 + 16>];
--:-:-:-:1      LDS.U.128 jl0Ix0, [readIs + 4x<0*32*36 + 00>];
--:-:6:-:1      LDS.U.128 jl0Fy0, [readFs + 4x<0*32*36 + 00>];

--:-:-:-:1      STS [writeS + 4x<32*(5*6 + 5)>], F55;

--:-:-:-:1      STS [writeS + 4x<32*(0*6 + 0)>], F00;
--:-:-:-:1      STS [writeS + 4x<32*(0*6 + 1)>], F01;
--:-:-:-:1      STS [writeS + 4x<32*(0*6 + 2)>], F02;
--:-:-:-:1      STS [writeS + 4x<32*(0*6 + 3)>], F03;
--:-:-:-:1      STS [writeS + 4x<32*(0*6 + 4)>], F04;
--:-:-:-:1      STS [writeS + 4x<32*(0*6 + 5)>], F05;

--:-:-:-:1      STS [writeS + 4x<32*(1*6 + 0)>], F10;
--:-:-:-:1      STS [writeS + 4x<32*(1*6 + 1)>], F11;
--:-:-:-:1      STS [writeS + 4x<32*(1*6 + 2)>], F12;
--:-:-:-:1      STS [writeS + 4x<32*(1*6 + 3)>], F13;
--:-:-:-:1      STS [writeS + 4x<32*(1*6 + 4)>], F14;
--:-:-:-:1      STS [writeS + 4x<32*(1*6 + 5)>], F15;

--:-:-:-:1      STS [writeS + 4x<32*(2*6 + 0)>], F20;
--:-:-:-:1      STS [writeS + 4x<32*(2*6 + 1)>], F21;
--:-:-:-:1      STS [writeS + 4x<32*(2*6 + 2)>], F22;
--:-:-:-:1      STS [writeS + 4x<32*(2*6 + 3)>], F23;
--:-:-:-:1      STS [writeS + 4x<32*(2*6 + 4)>], F24;
--:-:-:-:1      STS [writeS + 4x<32*(2*6 + 5)>], F25;

--:-:-:-:1      STS [writeS + 4x<32*(3*6 + 0)>], F30;
--:-:-:-:1      STS [writeS + 4x<32*(3*6 + 1)>], F31;
--:-:-:-:1      STS [writeS + 4x<32*(3*6 + 2)>], F32;
--:-:-:-:1      STS [writeS + 4x<32*(3*6 + 3)>], F33;
--:-:-:-:1      STS [writeS + 4x<32*(3*6 + 4)>], F34;
--:-:-:-:1      STS [writeS + 4x<32*(3*6 + 5)>], F35;

--:-:-:-:1      STS [writeS + 4x<32*(4*6 + 0)>], F40;
--:-:-:-:1      STS [writeS + 4x<32*(4*6 + 1)>], F41;
--:-:-:-:1      STS [writeS + 4x<32*(4*6 + 2)>], F42;
--:-:-:-:1      STS [writeS + 4x<32*(4*6 + 3)>], F43;
--:-:-:-:1      STS [writeS + 4x<32*(4*6 + 4)>], F44;
--:-:-:-:1      STS [writeS + 4x<32*(4*6 + 5)>], F45;
</SCHEDULE_BLOCK>

<SCHEDULE_BLOCK>
20:-:-:-:1      IADD   track0.CC, track0, param_RSK2p;
--:-:-:-:1      IADD.X track1,    track1, RZ;
<ORDERED>
[+
    our ($dtype, $dsize, $SK, $K);
    my %insert = (
        j0c0  => "--:-:-:-:1      LDS.U.128 jl1Fy4, [readFs + 4x<1*32*36 + 16>];\n",
        j0c1  => "--:-:-:-:1      LDS.U.128 jl1Ix0, [readIs + 4x<1*32*36 + 00>];\n",
        j0c15 => "--:-:5:-:1      LDS.U.128 jl1Fy0, [readFs + 4x<1*32*36 + 00>];\n",

        j0c5  => "--:-:-:-:1      STS [writeS + 4x<32*(5*6 + 0)>], F50;\n",
        j0c7  => "--:-:-:-:1      STS [writeS + 4x<32*(5*6 + 1)>], F51;\n",
        j0c9  => "--:-:-:-:1      STS [writeS + 4x<32*(5*6 + 2)>], F52;\n",
        j0c11 => "--:-:-:-:1      STS [writeS + 4x<32*(5*6 + 3)>], F53;\n",
        j0c13 => "--:-:-:-:1      STS [writeS + 4x<32*(5*6 + 4)>], F54;\n",

        j1c1  => "--:-:-:-:1  \@P0 LDG.E.CI.$dtype f00, [track + ${dsize}x<0*3*$K + 0*$K>];\n",
        j1c2  => "--:-:-:-:1  \@P0 LDG.E.CI.$dtype f01, [track + ${dsize}x<0*3*$K + 1*$K>];\n",
        j1c3  => "--:-:1:-:1  \@P0 LDG.E.CI.$dtype f02, [track + ${dsize}x<0*3*$K + 2*$K>];\n",

        j1c4  => "--:-:-:-:1  \@P0 LDG.E.CI.$dtype f10, [track + ${dsize}x<1*3*$K + 0*$K>];\n",
        j1c5  => "--:-:-:-:1  \@P0 LDG.E.CI.$dtype f11, [track + ${dsize}x<1*3*$K + 1*$K>];\n",
        j1c6  => "--:-:2:-:1  \@P0 LDG.E.CI.$dtype f12, [track + ${dsize}x<1*3*$K + 2*$K>];\n",

        j1c7  => "--:-:-:-:1  \@P0 LDG.E.CI.$dtype f20, [track + ${dsize}x<2*3*$K + 0*$K>];\n",
        j1c8  => "--:-:-:-:1  \@P0 LDG.E.CI.$dtype f21, [track + ${dsize}x<2*3*$K + 1*$K>];\n",
        j1c9  => "--:-:3:-:1  \@P0 LDG.E.CI.$dtype f22, [track + ${dsize}x<2*3*$K + 2*$K>];\n",
    );

    my @cOrder;
    my @swirl = ([0,2],[1,2],[1,0],[0,0]);
    foreach my $xy ([0,0],[0,1],[2,1],[2,0],[2,4],[2,5],[0,5],[0,4])
    {
        my ($x, $y) = @$xy;
        push @cOrder, [$x + $_->[0], $y + $_->[1]] foreach @swirl;
    }
    my $out;
    foreach my $j (0 .. 1)
    {
        foreach my $c (0 .. 31)
        {
            my ($x,$y) = @{$cOrder[$c]};

            my $ins    = $insert{"j${j}c$c"} || '';

            my $wait   = $c == 0 && $j == 1 ? "10" : '--';

            my $ctrl   = "$wait:-:-:-:1";

            $out .= sprintf "%s      FFMA clx%dy%d, jl%dIx%d, jl%dFy%d, clx%dy%d;\n%s", $ctrl,  $x,$y,  $j,$x,  $j,$y,  $x,$y,  $ins;
        }
    }
    return $out;
+]
</ORDERED>

</SCHEDULE_BLOCK>
--:-:-:-:1      IADD readFs, readFs, -swapBuf;
--:-:-:-:1      IADD readIs, readIs, -swapBuf;
--:-:-:-:0      IADD writeS, writeS,  swapBuf;
--:-:-:Y:5      BAR.SYNC 0;
--:-:-:-:0      IADD swapBuf, RZ,    -swapBuf;
--:-:-:Y:5  @P1 BRA.U FILTER_LOOP;


LOAD_FINISH:

[-
    our $trans1 = "0.244140625";
    our $trans2 = "0.625";
    our $trans3 = "0.390625";
-]

<INCLUDE file="xconv_winograd_4x4_3x3_32x32_common.sass"/>
